/*
* $Id: BluetoothSync.java 337 2011-09-28 06:13:53Z volok-aleksej@yandex.ru $
*
* Copyright 2008-2011 by Volokitin Alexey
* All rights reserved
*
*/
package apiary.bt;

import apiary.db.*;
import apiary.db.ChangesStore.ChangesRecord;
import apiary.db.managers.DBManager;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
import javax.microedition.io.Connector;
import javax.microedition.lcdui.Form;
import javax.microedition.rms.RecordEnumeration;
import javax.microedition.rms.RecordStore;
import javax.microedition.rms.RecordStoreException;

public class BluetoothSync
{
    public static int POINT_TYPE = 1;
    public static int FAMILY_TYPE = 2;
    public static int JOURNAL_TYPE = 3;
    public static int INSPECT_TYPE = 4;
    public static int HOUSING_TYPE = 5;
    public static int QUEEN_BEE_TYPE = 6;
    public static int USER_FIELD_TYPE = 7;
    public static int FIELD_VALUE_TYPE = 8;
    public static int TYPE_FRAME_TYPE = 9;
    public static int TYPE_HOUSING_TYPE = 10;

    private String connUrl;
    private DataOutputStream outputStream;
    private DataInputStream inputStream;
    private Hashtable stores;
    private ChangesStore changesStore;

    BluetoothSync(String url) throws IOException, RecordStoreException {
        connUrl = url;
        stores = new Hashtable();
        hashStore();
        changesStore = new ChangesStore();
    }

    public void stop() throws IOException {
        if(outputStream != null){
            outputStream.close();
        }
        if(inputStream != null){
            inputStream.close();
        }
    }

    public void outputData() throws IOException{
        outputStream = Connector.openDataOutputStream(connUrl);
        byte ver[] = {'1','.','0','.','0'};
        outputStream.write(ver);
        Vector records = changesStore.getRecords();
        outputStream.writeInt(records.size());
        for(int i = 0; i < records.size(); i++) {
            ChangesRecord record = (ChangesRecord) records.elementAt(i);
            outputStream.writeInt(record.type);
            outputStream.writeInt(record.value.length);
            outputStream.write(record.value);
        }
        outputStream.close();
    }

    public void inputData() throws IOException, RecordStoreException {
        inputStream = Connector.openDataInputStream(connUrl);
        byte[] val = new byte[5];
        inputStream.read(val);
        if(val[0] == '1' &&
           val[1] == '.' &&
           val[2] == '0' &&
           val[3] == '.' &&
           val[4] == '0')
        {
            RecordStore tempStore = RecordStore.openRecordStore("sync_input", true);
            if(tempStore.getNumRecords() != 0) {
                tempStore.closeRecordStore();
                RecordStore.deleteRecordStore("sync_input");
                tempStore = RecordStore.openRecordStore("sync_input", true);
            }
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            DataOutputStream dos = new DataOutputStream(baos);
            while(true){
                int type = inputStream.readInt();
                if(type == 0)
                    break;

                DBStore dbstore = (DBStore) stores.get(new Integer(type));
                DBRecord record = dbstore.getRecord();
                record.setData(inputStream);
                byte[] data = record.getData();

                baos.reset();
                dos.writeInt(type);
                baos.write(data, 0, data.length);
                byte[] tempData = baos.toByteArray();
                tempStore.addRecord(tempData, 0, tempData.length);

            }
            tempStore.closeRecordStore();
        } else {
            throw new RecordStoreException("input error");
        }
        inputStream.close();
    }

    public void saveData() throws RecordStoreException, IOException {
        changesStore.removeAllElements();
        Enumeration enumStores = stores.elements();
        while(enumStores.hasMoreElements()){
            DBStore store = (DBStore) enumStores.nextElement();
            store.removeAllElements();
        }
        RecordStore tempStore = RecordStore.openRecordStore("sync_input", true);
        RecordEnumeration enumRec = tempStore.enumerateRecords(null, null, false);
        while(enumRec.hasNextElement()) {
            byte[] tempData = enumRec.nextRecord();
            ByteArrayInputStream bais = new ByteArrayInputStream(tempData);
            DataInputStream dis = new DataInputStream(bais);
            int id = dis.readInt();
            DBStore dbstore = (DBStore) stores.get(new Integer(id));
            DBRecord record = dbstore.getRecord();
            record.setData(dis);
            byte[] data = record.getData();
            dbstore.addRecord(data, data.length);
        }
        tempStore.closeRecordStore();
        DBManager.getInstance().resetDBManagers();
    }

    private void hashStore() throws RecordStoreException {
        PointStore point = new PointStore();
        stores.put(new Integer(POINT_TYPE),point);
        FamilyStore family =new FamilyStore();
        stores.put(new Integer(FAMILY_TYPE), family);
        JournalStore journal = new JournalStore();
        stores.put(new Integer(JOURNAL_TYPE), journal);
        InspectStore inspect = new InspectStore();
        stores.put(new Integer(INSPECT_TYPE), inspect);
        HousingStore housing = new HousingStore();
        stores.put(new Integer(HOUSING_TYPE), housing);
        QueenBeeStore queenBee = new QueenBeeStore();
        stores.put(new Integer(QUEEN_BEE_TYPE), queenBee);
        UserFieldsStore userFields = new UserFieldsStore();
        stores.put(new Integer(USER_FIELD_TYPE), userFields);
        FieldsValueStore fieldsValue = new FieldsValueStore();
        stores.put(new Integer(FIELD_VALUE_TYPE), fieldsValue);
        TypeStore typeStore = new TypeStore("db_type_frame");
        stores.put(new Integer(TYPE_FRAME_TYPE), typeStore);
        typeStore = new TypeStore("db_type_frame");
        stores.put(new Integer(TYPE_HOUSING_TYPE), typeStore);
    }
}
